package xin.marcher.module.quality.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import xin.marcher.module.common.constants.quality.SurveyTaskMaterialsConstants;
import xin.marcher.module.common.core.PageResult;
import xin.marcher.module.common.enums.inventory.InventoryExceptionCode;
import xin.marcher.module.common.enums.quality.MaterialStatusEnum;
import xin.marcher.module.common.enums.quality.QualityExceptionCode;
import xin.marcher.module.common.exception.BaseBizException;
import xin.marcher.module.construction.domain.dto.SaleSkuDTO;
import xin.marcher.module.construction.domain.request.QuerySaleSkuRequest;
import xin.marcher.module.quality.converter.SurveyTaskConverter;
import xin.marcher.module.quality.converter.SurveyTaskMaterialsRelationConverter;
import xin.marcher.module.quality.domain.dto.ItemQualityControlSurveyTaskDTO;
import xin.marcher.module.quality.domain.dto.ItemQualityControlSurveyTaskResultDO;
import xin.marcher.module.quality.domain.dto.ItemQualityControlSurveyTaskToSellerDTO;
import xin.marcher.module.quality.domain.dto.ItemSurveyTaskDetailDTO;
import xin.marcher.module.quality.domain.entity.ItemQualityControlSurveyDO;
import xin.marcher.module.quality.domain.entity.ItemQualityControlSurveyTaskDO;
import xin.marcher.module.quality.domain.entity.SurveyTaskMaterialsRelationDO;
import xin.marcher.module.quality.domain.request.ItemQualityControlSurveyTaskRequest;
import xin.marcher.module.quality.domain.request.SurveyFormRequest;
import xin.marcher.module.quality.domain.request.SurveyTaskRequest;
import xin.marcher.module.quality.oss.OssManager;
import xin.marcher.module.quality.remote.ProductRemote;
import xin.marcher.module.quality.repository.ItemQualityControlRepository;
import xin.marcher.module.quality.repository.OperatorCategoryRelationRepository;
import xin.marcher.module.quality.repository.SurveyRepository;
import xin.marcher.module.quality.service.ItemQualityControlSurveyTaskService;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import static xin.marcher.module.common.constants.diplomacy.BaseConstants.PAGE_SIZE_100;

/**
 *
 */
@Slf4j
@Service
public class ItemQualityControlSurveyTaskServiceImpl implements ItemQualityControlSurveyTaskService {
    @Autowired
    private SurveyRepository surveyRepository;

    @Autowired
    private OssManager ossManager;

    @Autowired
    private SurveyTaskConverter surveyTaskConverter;

    @Autowired
    private SurveyTaskMaterialsRelationConverter relationConverter;

    @Autowired
    private ProductRemote productRemote;

    @Autowired
    private ItemQualityControlRepository itemQualityControlRepository;

    @Autowired
    private OperatorCategoryRelationRepository operatorCategoryRelationRepository;

    /**
     * 获取调查任务列表
     *
     * @param request
     * @return
     */
    @Override
    public List<ItemQualityControlSurveyTaskDTO> surveyTaskList(ItemQualityControlSurveyTaskRequest request) {
        // 参数检查
        checkQueryParams(request);
        return itemQualityControlRepository.surveyTaskList(request);
    }

    /**
     * 调查员认领任务
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ItemQualityControlSurveyTaskResultDO claimedSurveyTask(ItemQualityControlSurveyTaskRequest request) {
        // 参数检查
        checkParams(request);
        // 调查池中的数据
        ItemQualityControlSurveyDO itemQualityControlSurveyDO = itemQualityControlRepository.querySurveyPool(request);
        // 调查员是否有权限认领该任务
        operatorCategoryRelationRepository.checkOperatorPermission(itemQualityControlSurveyDO, request);
        // 如果有权限，则进行认领
        itemQualityControlRepository.claimedSurveyTask(itemQualityControlSurveyDO, request);
        return new ItemQualityControlSurveyTaskResultDO(Boolean.TRUE);
    }

    /**
     * 分页查询参数检查
     *
     * @param request
     */
    private void checkQueryParams(ItemQualityControlSurveyTaskRequest request) {
        if (Objects.isNull(request)) {
            throw new BaseBizException(InventoryExceptionCode.PARAM_CHECK_ERROR, InventoryExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }

        if (request.getPageSize() > PAGE_SIZE_100) {
            throw new BaseBizException(InventoryExceptionCode.PARAM_CHECK_ERROR, InventoryExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }

    /**
     * 检查参数
     *
     * @param request
     */
    private void checkParams(ItemQualityControlSurveyTaskRequest request) {
        if (Objects.isNull(request)) {
            throw new BaseBizException(InventoryExceptionCode.PARAM_CHECK_ERROR, InventoryExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }

        if (Objects.isNull(request.getSurveyId())) {
            throw new BaseBizException(InventoryExceptionCode.PARAM_CHECK_ERROR, InventoryExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }

    /**
     * 查询调查任务列表
     *
     * @param request
     * @return
     */
    @Override
    public PageResult<ItemQualityControlSurveyTaskDTO> surveyTaskPage(SurveyTaskRequest request) {
        // 校验userId是否为空
        checkQueryParams(request);

        // 查询调查单列表
        return surveyRepository.querySurveyTaskList(request);
    }

    /**
     * 查询调查单详情
     *
     * @param request
     * @return
     */
    @Override
    public ItemSurveyTaskDetailDTO surveyTaskDetail(SurveyTaskRequest request) {
        checkSurveyTaskParam(request);
        // 查询调查单
        ItemQualityControlSurveyTaskDO surveyTaskDO = surveyRepository.querySurveyTask(request);

        if (Objects.isNull(surveyTaskDO)) {
            throw new BaseBizException("查不到调查任务信息！");
        }
        // 查询调查单资质材料信息
        SurveyTaskMaterialsRelationDO materialsRelationDO =
                surveyRepository.queryMaterialsRelation(request);
        if (Objects.isNull(materialsRelationDO)) {
            throw new BaseBizException("查不到调查任务材料信息！");
        }
        // 构建查询商品详情信息请求request
        QuerySaleSkuRequest skuRequest = new QuerySaleSkuRequest();
        skuRequest.setSellerId(surveyTaskDO.getSellerId().toString());
        Set<String> skuSet = new HashSet<>();
        skuSet.add(surveyTaskDO.getSkuId());
        skuRequest.setSkuIdSet(skuSet);

        // 查询商品详情信息
        SaleSkuDTO skuDetail = productRemote.getSkuDetail(skuRequest);

        if (Objects.isNull(skuDetail)) {
            throw new BaseBizException("获取调查单对应商品详情信息失败");
        }
        return ItemSurveyTaskDetailDTO.builder()
                .materialsRelationDTO(relationConverter.converterDOToDTO(materialsRelationDO))
                .problemType(surveyTaskDO.getProblemType())
                .riskLevel(surveyTaskDO.getRiskLevel())
                .skuName(surveyTaskDO.getSkuName())
                .surveyFormContent(surveyTaskDO.getSurveyFormContent())
                .skuInfoDTO(skuDetail)
                .build();
    }

    /**
     * 发送调查单
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean sendSurveyForm(SurveyTaskRequest request) {
        checkSendSurveyTaskParam(request);
        surveyRepository.sendSurveyForm(request);

        // 发送MQ消息给卖家，经过消息中心，对外推送消息
        // 注：此处借助消息中心发送消息，不在业务代码中直接耦合
        // 在执行发送调查单操作之后，消息中心监听到发送调查单操作，会执行推送消息到MQ的操作
        // quality服务监听MQ消息，执行推送消息逻辑
        // 对应listener:xin.marcher.module.quality.mq.consumer.listener.SurveyFormSendListener
        return true;
    }

    /**
     * 审核资质证明
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean auditQualityMaterials(SurveyTaskRequest request) {
        // 检查资质证明相关的参数是否正确
        checkAuditMaterialsParam(request);
        // 执行审核操作
        surveyRepository.auditQualityMaterials(request);
        // 此处借助消息中心推送消息，如果监听到状态变更是继续上传证明资质材料，消息中心会发送消息到MQ
        // quality监听对应的topic，如果是继续发送资质材料，则需要推送消息到卖家
        // xin.marcher.module.quality.mq.consumer.listener.SurveyFormSendListener，listener中执行推送消息任务
        return true;
    }

    /**
     * 开启/关闭商家提供资质期限
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean changeDeadlineStatus(SurveyTaskRequest request) {
        checkChangeDeadlineStatusParam(request);
        surveyRepository.changeDeadlineStatus(request);
        return true;
    }

    /**
     * 变更商家提供资质证明期限
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateDeadline(SurveyTaskRequest request) {
        checkChangeDeadlineParam(request);
        surveyRepository.updateSurveyDeadline(request);
        return true;
    }

    /**
     * 卖家查询调查单详情
     *
     * @param request
     * @return
     */
    @Override
    public PageResult<ItemQualityControlSurveyTaskToSellerDTO> surveyFormList(SurveyFormRequest request) {
        checkSurveyFormListParam(request);
        return surveyRepository.querySurveyTaskListToSeller(request);
    }

    /**
     * 卖家上传资料
     *
     * @param request
     * @param file
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean uploadQualityMaterials(SurveyFormRequest request, MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            checkUploadMaterialParam(request);
            // 根据sellerId查询当前卖家操作的任务是否属于当前卖家
            SurveyTaskRequest taskRequest = SurveyTaskRequest.builder()
                    .surveyId(request.getSurveyId())
                    .sellerId(request.getSellerId())
                    .build();
            ItemQualityControlSurveyTaskDO taskDO = surveyRepository.querySurveyTask(taskRequest);

            // 执行上传操作
            // 这一步返回的是可以直接下载的url
            // 所以，也可以直接选择使用返回的url作为下载链接，返回给前端展示
            ossManager.uploadFile(inputStream, SurveyTaskMaterialsConstants.DEFAULT_PATH, file.getOriginalFilename());
            // 修改上传文件状态
            taskDO.setQualityUploadStatus(MaterialStatusEnum.UPLOADED.getCode());

            // 先判断是不是第一次上传，如果是则新增一条材料与调查任务关系
            SurveyTaskMaterialsRelationDO relationDO = surveyRepository.queryMaterialsRelationBySellerId(request);
            if (Objects.isNull(relationDO)) {
                // 增加一条资料与调查任务关联关系
                relationDO = new SurveyTaskMaterialsRelationDO();
                relationDO.setSurveyId(request.getSurveyId());
                relationDO.setQualityMaterials(file.getOriginalFilename());
                relationDO.initCommon();
                // 添加文件与调查任务关联关系
                surveyRepository.addQualityMaterialRelation(relationDO);
            }
            // 如果不是，就修改一下地址
            relationDO.setQualityMaterials(file.getOriginalFilename());
            relationDO.initCommon();
            // 添加文件与调查任务关联关系
            surveyRepository.updateQualityMaterialRelation(relationDO);
            // 修改调查任务文件上传状态
            surveyRepository.uploadQualityMaterials(taskDO);
            return true;
        } catch (IOException e) {
            throw new BaseBizException("证明材料上传出错", JSON.toJSONString(e));
        }
    }

    /**
     * 调查员下载资料
     *
     * @param request
     * @return
     */
    @Override
    public void downLoadQualityMaterials(SurveyTaskRequest request) {
        checkSurveyTaskParam(request);
        SurveyTaskMaterialsRelationDO relationDO = surveyRepository.queryMaterialsRelation(request);
        // 注：工具类提供三种下载方法：
        // (1)下载至系统配置文件夹方法，即本系统采取的下载方法
        // (2)上传过程生成的直接下载链接，直接返回前端，不需要额外写下载方法，可直接通过链接下载
        // (3)获取文件后，通过response，返回给前端浏览器下载到用户本地，具体方法为ossManager.downloadFile
        ossManager.download(SurveyTaskMaterialsConstants.DEFAULT_PATH + relationDO.getQualityMaterials(),
                SurveyTaskMaterialsConstants.LOCAL_PATH + relationDO.getQualityMaterials());
    }

    private void checkSurveyFormListParam(SurveyFormRequest request) {
        if (Objects.isNull(request)) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }

        if (Objects.isNull(request.getSellerId())) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }


    private void checkChangeDeadlineParam(SurveyTaskRequest request) {
        checkSurveyTaskParam(request);

        if (Objects.isNull(request.getDeadline())) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }

    private void checkChangeDeadlineStatusParam(SurveyTaskRequest request) {
        checkSurveyTaskParam(request);

        if (Objects.isNull(request.getDeadlineStatus())) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }

    private void checkAuditMaterialsParam(SurveyTaskRequest request) {
        checkSurveyTaskParam(request);

        if (Objects.isNull(request.getAuditStatus())) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }

    /**
     * 校验参数是否正确
     *
     * @param request
     */
    private void checkSendSurveyTaskParam(SurveyTaskRequest request) {

        checkSurveyTaskParam(request);

        if (Objects.isNull(request.getSurveyForm())) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }

    /**
     * 校验参数是否正确
     *
     * @param request
     */
    private void checkSurveyTaskParam(SurveyTaskRequest request) {

        checkQueryParams(request);

        if (Objects.isNull(request.getSurveyId())) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());

        }
    }

    private void checkUploadMaterialParam(SurveyFormRequest request) {

        if (Objects.isNull(request)) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
        if (Objects.isNull(request.getSurveyId())) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
        if (Objects.isNull(request.getSellerId())) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }

    /**
     * 校验参数是否正确
     *
     * @param request
     */
    private void checkQueryParams(SurveyTaskRequest request) {
        if (Objects.isNull(request)) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }

        if (Objects.isNull(request.getUserId())) {
            throw new BaseBizException(QualityExceptionCode.PARAM_CHECK_ERROR, QualityExceptionCode.PARAM_CHECK_ERROR.getErrorCode());
        }
    }
}
